﻿namespace LiSA_Server.Base.AbstractActioners
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Exceptions;

    public abstract class BaseActioner
    {
        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <param name="action">an action that can fail</param>
        public void WithTryCatchErrorLog(Action action)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                throw new ActionFailedException(string.Format("{0}\n\n{1}", e.Message, e.StackTrace));
            }
        }

        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <typeparam name="TZ">return value type</typeparam>        
        /// <param name="action">an action that can fail</param>
        /// <returns>return params for the action</returns>
        public TZ WithTryCatchErrorLog<TZ>(Func<TZ> action)
        {
            TZ result = default(TZ);

            this.WithTryCatchErrorLog(() => { result = action(); });

            return result;
        }

        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <param name="action">an action that can fail</param>
        /// <param name="callbackIfException">action to be done if we have an error</param>
        public void WithTryCatchErrorLog(Action action, Action callbackIfException)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                callbackIfException();
                throw new ActionFailedException(string.Format("{0}\n\n{1}", e.Message, e.StackTrace));
            }
        }

        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <typeparam name="TZ">return value type</typeparam>        
        /// <param name="action">an action that can fail</param>
        /// <param name="callbackIfException">action to be done if we have an error</param>
        /// <returns>return params for the action</returns>
        public TZ WithTryCatchErrorLog<TZ>(Func<TZ> action, Action callbackIfException)
        {
            TZ result = default(TZ);

            this.WithTryCatchErrorLog(() => { result = action(); }, callbackIfException);

            return result;
        }

        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <param name="action">an action that can fail</param>
        /// <param name="callbackIfExceptions">actions to be done if we have an error</param>
        public void WithTryCatchErrorLog(Action action, List<Action> callbackIfExceptions)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                foreach (var callbackIfException in callbackIfExceptions)
                {
                    callbackIfException();
                }

                throw new ActionFailedException(string.Format("{0}\n\n{1}", e.Message, e.StackTrace));
            }
        }

        /// <summary>
        /// Surrounds a method with try-catch and logs errors
        /// </summary>
        /// <typeparam name="TZ">return value type</typeparam>        
        /// <param name="action">an action that can fail</param>
        /// <param name="callbackIfExceptions">actions to be done if we have an error</param>
        /// <returns>return params for the action</returns>
        public TZ WithTryCatchErrorLog<TZ>(Func<TZ> action, List<Action> callbackIfExceptions)
        {
            TZ result = default(TZ);

            this.WithTryCatchErrorLog(() => { result = action(); }, callbackIfExceptions);

            return result;
        }


        public bool IsGuidNullOrEmpty(Guid val)
        {
            if (val == null || val == Guid.Empty)
            {
                return true;
            }

            return false;
        }

        public bool IsGuidNullOrEmpty(Guid? val)
        {
            if (val == null || !val.HasValue || val.Value == Guid.Empty)
            {
                return true;
            }

            return false;
        }

        public bool IsDateTimeNullOrEmpty(DateTime val)
        {
            if (val == null || val == new DateTime(0))
            {
                return true;
            }

            return false;
        }

        public bool IsDateTimeNullOrEmpty(DateTime? val)
        {
            if (val == null || !val.HasValue || val.Value == new DateTime(0))
            {
                return true;
            }

            return false;
        }

        public bool IsTimeSpanNullOrEmpty(TimeSpan val)
        {
            if (val == null || val == new TimeSpan(0))
            {
                return true;
            }

            return false;
        }

        public bool IsTimeSpanNullOrEmpty(TimeSpan? val)
        {
            if (val == null || !val.HasValue || val.Value == new TimeSpan(0))
            {
                return true;
            }

            return false;
        }

        public bool IsListNullOrEmpty<T>(List<T> list)
        {
            if (list == null || !list.Any())
            {
                return true;
            }

            return false;
        }
    }
}
